/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "属性.h"

#include <zlib.h>


#include "core/动画/an_曲线.h"
#include "纹理/纹理.h"

#include "S_Object.h"


#ifdef _DEBUG
#define ZLIB_BASE_PATH "D:/U/Project/packages/zlib-msvc14-x64.1.2.11.7795/build/native/lib_release/"
#else
#define ZLIB_BASE_PATH "D:/U/Project/packages/zlib-msvc14-x64.1.2.11.7795/build/native/lib_release/"
#endif // DEBUG

//#pragma comment(lib, ZLIB_BASE_PATH "zlib.lib")
#pragma comment(lib, ZLIB_BASE_PATH "zlibstatic.lib")



void f_prop_Release(S_Props& prop) {
	DEF_release_Props_UI_Ptr(prop);
	prop.m_UI = nullptr;


	
	switch (prop.m_Type) {
		
		case E_值类型::e_Type_Operator:
			if(prop.m_风格属性) delete prop.m_风格属性;
			return;
		case E_值类型::e_Type_Enum:
			f_release_EnumProp(prop);
			break;
		case E_值类型::e_Type_MapPtr_Array1D:
			f_StrIndexProp_release(prop);
			break;
		case E_值类型::e_Type_映射引用_2D:
			f_prop_映射引用2D_release(prop);
			break;
		case E_值类型::e_Type_UI8_Array1D:
			delete[] (S_PropVecU8*)prop.m_Value;
			return;
		case E_值类型::e_Type_Bool_1D:
			delete[] (S_PropVecBool*)prop.m_Value;
			return;
		case E_值类型::e_Type_PropContainer:
			delete (S_PropContainer*)prop.m_Value;
			return;
		case E_值类型::e_Type_PropList:
			delete (S_PropList*)prop.m_Value;
			return;
		case E_值类型::e_Type_2D曲线:
			f_an_销毁曲线A((S_曲线*)prop.m_Value);
			return;
		case E_值类型::e_Type_2D曲线1D:
			f_an_销毁曲线层((S_动画曲线组*)prop.m_Value);
			return;
		case E_值类型::e_Type_ObjectContainerMap:
			delete prop.m_Value;
			return;
		
		case E_值类型::e_Type_轨道容器: {
			auto& 轨道 = f_prop_轨道(prop);
			for (auto& e : 轨道.m_轨道层) {
				for (auto& b : e->m_层采样条) {
					free(b);
				}
			}
			delete prop.m_Value;
			return;
		}
		//case E_值类型::e_Type_ObjectOps:
		//	return;

		case E_值类型::e_Type_ContainerBool:
		case E_值类型::e_Type_ContainerF32:
		case E_值类型::e_Type_ContainerI8:
		case E_值类型::e_Type_ContainerI32:
		case E_值类型::e_Type_ContainerUI32:
		case E_值类型::e_Type_ContainerVec2:
		case E_值类型::e_Type_ContainerVec3:
		case E_值类型::e_Type_ContainerVec4:
		case E_值类型::e_Type_ContaineriVec2:
		case E_值类型::e_Type_ContaineriVec3:
		case E_值类型::e_Type_ContaineriVec4:
		case E_值类型::e_Type_ContainerBound:
		case E_值类型::e_Type_ContainerValue: {
			S_PropContainer& 容器 = f_prop_Container(prop);
			uint32 num = 容器.m_Item.size();
			for (uint32 i = 0; i < num; ++i) {
				f_prop_Release(容器.m_Item[i]);
			}
			//delete (S_PropContainer*)prop.m_Value;
			break;
		}
		default:
			break;
	}

	if (prop.m_值映射类型 == E_属性值映射方式::e_属性值映射_外部指针) return;
	

	switch (prop.m_Type) {
		case E_值类型::e_Type_TexSets:
			auto e = f_prop_纹理集(prop);
			f_纹理集_销毁(e.m_纹理集);
			break;

		case E_值类型::e_Type_Enum:
			free(f_prop_enumItem(prop).m_当前选项);
			break;
	}
	
	free(prop.m_Value);
}



std::vector<std::u16string> f_prop_EnumItem_Names(const S_Props& prop) {
	const S_Prop枚举项 item = f_prop_位域枚举项(prop);
	std::vector<std::u16string> 项名称;
	for (uint32 i = 0; i < item.m_数量; ++i) {
		项名称.push_back(item.m_Names[i]);
	}
	return 项名称;
}



S_Props f_alloc_FlagBitsUI8Prop(uint8* data, std::u16string name, uint8 默认选项, fp_PropUpdate fn_update, bool 是否展开) {
	E_属性值映射方式 映射类型;
	if (data == nullptr) {
		data = (uint8*)malloc(sizeof(uint8));
		(*data) = 默认选项;

		映射类型 = E_属性值映射方式::e_属性值映射_独立创建;
	}
	else {
		映射类型 = E_属性值映射方式::e_属性值映射_外部指针;
	}
	S_Props prop = f_prop_init(E_值类型::e_Type_UI8位域枚举, data, name, 映射类型);
	prop.m_值元素个数 = 8;


	DEF_alloc_Props_UI_Ptr(prop);
	prop.m_UI->m_Update = fn_update;
	return prop;
}






std::u16string f_core_get属性到文本(S_Props prop, uint8 分量) {
	std::u16string text;

	switch (prop.m_Type) {
		case E_值类型::e_Type_I8: text = f_整数值转宽字符串(*(int8*)prop.m_Value); break;
		case E_值类型::e_Type_UI8: text = f_整数值转宽字符串(*(uint8*)prop.m_Value); break;
		case E_值类型::e_Type_I16: text = f_整数值转宽字符串(*(int16*)prop.m_Value); break;
		case E_值类型::e_Type_UI16: text = f_整数值转宽字符串(*(uint16*)prop.m_Value); break;
		case E_值类型::e_Type_I32: text = f_整数值转宽字符串(*(int32*)prop.m_Value); break;
		case E_值类型::e_Type_UI32: text = f_整数值转宽字符串(*(uint32*)prop.m_Value); break;
			//case E_值类型::e_插座Type_I64: text = f_整数值转宽字符串w(*(int64*)editBox->m_Value.m_Value); break;
		case E_值类型::e_Type_UI64: text = f_整数值转宽字符串64(*(uint64*)prop.m_Value); break;

		case E_值类型::e_Type_F32: text = f_浮点数值转宽字符串(*(float32*)prop.m_Value); break;
		case E_值类型::e_Type_RGB:
		case E_值类型::e_Type_Vec2:
		case E_值类型::e_Type_Vec3:
		case E_值类型::e_Type_Vec4: text = f_浮点数值转宽字符串(((float32*)prop.m_Value)[分量]); break;

		case E_值类型::e_Type_iVec2:
		case E_值类型::e_Type_iVec3:
		case E_值类型::e_Type_iVec4: text = f_整数值转宽字符串(((int32*)prop.m_Value)[分量]); break;
		case E_值类型::e_Type_uVec2:
		case E_值类型::e_Type_uVec3:
		case E_值类型::e_Type_uVec4: text = f_整数值转宽字符串(((uint32*)prop.m_Value)[分量]); break;
	}

	return text;
}

void f_core_字符串转换到属性(S_Props& prop, const std::u16string& text, uint8 分量) {
	switch (prop.m_Type) {
		case E_值类型::e_Type_I8: f_prop_I8(prop) = f_字符串转I32(text); break;
		case E_值类型::e_Type_UI8: f_prop_UI8(prop) = f_字符串转I32(text); break;
		case E_值类型::e_Type_I16: f_prop_I16(prop) = f_字符串转I32(text); break;
		case E_值类型::e_Type_UI16: f_prop_UI16(prop) = f_字符串转I32(text); break;
		case E_值类型::e_Type_I32: f_prop_I32(prop) = f_字符串转I32(text); break;
		case E_值类型::e_Type_UI32: f_prop_UI32(prop) = f_字符串转I32(text); break;
			//case E_值类型::e_插座Type_I64: text = f_整数值转宽字符串w(*(int64*)editBox->m_Value.m_Value); break;
		case E_值类型::e_Type_UI64: f_prop_UI64(prop) = f_字符串转I32(text); break;

		case E_值类型::e_Type_F32: f_prop_F32(prop) = f_字符串转F32(text); break;
		case E_值类型::e_Type_Vec2:
		case E_值类型::e_Type_Vec3:
		case E_值类型::e_Type_Vec4: ((float32*)prop.m_Value)[分量] = f_字符串转F32(text); break;
		case E_值类型::e_Type_iVec2:
		case E_值类型::e_Type_iVec3:
		case E_值类型::e_Type_iVec4: ((int32*)prop.m_Value)[分量] = f_字符串转I32(text); break;
		case E_值类型::e_Type_uVec2:
		case E_值类型::e_Type_uVec3:
		case E_值类型::e_Type_uVec4: ((uint32*)prop.m_Value)[分量] = f_字符串转I32(text); break;
	}
}

S_Props f_alloc_Object(std::map<std::u16string, struct S_Object*>* data, const std::u16string& name, const std::u16string& 当前项) {
    E_属性值映射方式 映射类型 = E_属性值映射方式::e_属性值映射_独立创建;

    S_MapObject* m = new S_MapObject;
    m->容器 = data;

    if (当前项.size() && data->find(当前项) != data->end()) {
        m->当前项 = {data->at(当前项), 当前项};
    }
    else {
        m->当前项 = {nullptr, u""};
    }


    S_Props prop = f_prop_init(E_值类型::e_Type_ObjectContainerMap, m, name, 映射类型);
    DEF_alloc_Props_UI_Ptr(prop);
    return prop;
}

void f_prop_ObjectMapSelect(S_Props& prop, const std::u16string& key) {
    auto& item = *f_prop_ObjectMap(prop);
    if (item.容器->find(key) != item.容器->end()) {
        item.当前项.当前对象 = item.容器->at(key);
        item.当前项.当前选项 = key;
    }
    else {
        item.当前项.当前对象 = nullptr;
        item.当前项.当前选项 = u"";
    }
}


S_Props f_alloc_ObjectArray(std::vector<struct S_Object*>* data, const std::u16string& name, struct S_Object* 当前项) {
	E_属性值映射方式 映射类型 = E_属性值映射方式::e_属性值映射_独立创建;

	S_ObjectArray* m = new S_ObjectArray;
	m->容器 = data;

	auto it = std::find(data->begin(), data->end(), 当前项);
	if (当前项 && it != data->end()) {
		m->当前项.当前对象 = 当前项;
	}
	else {
		m->当前项.当前对象 = nullptr;
	}
	m->当前项.当前选项 = u"";

	S_Props prop = f_prop_init(E_值类型::e_Type_ObjectContainerArray, m, name, 映射类型);
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

void f_prop_ObjectArraySelect(S_Props& prop, const std::u16string& key) {
	auto& item = *f_prop_ObjectArray(prop);
	auto it = std::find_if(item.容器->begin(), item.容器->end(), [&key](const S_Object* ob){
		return ob->m_Name == key;
	});

	if (it != item.容器->end()) {
		item.当前项.当前对象 = *it;
		item.当前项.当前选项 = key;
	}
	else {
		item.当前项.当前对象 = nullptr;
		item.当前项.当前选项 = u"";
	}
}


S_Object* f_prop_Object(S_Props& prop) {
	switch (prop.m_Type) {
		case E_值类型::e_Type_ObjectContainerMap: {
			return f_prop_ObjectMap(prop)->当前项.当前对象;
		}
		case E_值类型::e_Type_ObjectContainerArray: {
			return f_prop_ObjectArray(prop)->当前项.当前对象;
		}
		default:
			break;
	}
	return nullptr;
}

const S_Object* f_prop_Object(const S_Props& prop) {
	switch (prop.m_Type) {
		case E_值类型::e_Type_ObjectContainerMap: {
			return f_prop_ObjectMap(prop)->当前项.当前对象;
		}
		case E_值类型::e_Type_ObjectContainerArray: {
			return f_prop_ObjectArray(prop)->当前项.当前对象;
		}
		default:
			break;
	}
	return nullptr;
}


S_ObjectItem& f_prop_ObjectItem(S_Props& prop) {
	switch (prop.m_Type) {
		case E_值类型::e_Type_ObjectContainerMap: {
			return f_prop_ObjectMap(prop)->当前项;
		}
		case E_值类型::e_Type_ObjectContainerArray: {
			auto* item = f_prop_ObjectArray(prop);
			return f_prop_ObjectArray(prop)->当前项;
		}
		default:
			break;
	}
	S_ObjectItem 空{};
	return 空;
}

void f_prop_ObjectSelect(S_Props& prop, const std::u16string& key) {
	switch (prop.m_Type) {
		case E_值类型::e_Type_ObjectContainerMap: {
			f_prop_ObjectMapSelect(prop, key);
			break;
		}
		case E_值类型::e_Type_ObjectContainerArray: {
			f_prop_ObjectArraySelect(prop, key);
			break;
		}
	}
}

void f_prop_整数转行字符串(S_Props& prop, int32 value, const S_Props& 宽度, const S_Props& 填充字符, const S_Props& 字符方式) {
	uint32 num = f_prop_UI32(宽度);
	auto str = f_整数值转宽字符串(value, num);

	auto 空白字符 = f_prop_LineStr(填充字符);
	uint32 负数偏移 = 0;
	if (str.front() == L'-') {
		负数偏移 = 1;
		++num;
	}

	if (空白字符.size()) {
		空白字符 = 空白字符.front();
		for (uint32 i = str.size(); i < num; ++i) {
			str.insert(负数偏移, 空白字符);
		}
	}

	switch (f_prop_enum(字符方式)) {
		case 0: {
			if (负数偏移 == 0) str.insert(负数偏移, u"+"); 
			break;
		}
		case 2: {
			if (负数偏移 == 0) str.insert(负数偏移, u"+");
			else str.erase(0, 1);
			break;
		}
		case 1: {
			//if (负数偏移 == 0) str.insert(负数偏移, L"-");
			break;
		}
		
		case 3: {
			if (负数偏移 == 1) str.erase(0, 1);
			break;
		}
	}
	
	f_prop_LineStr(prop) = str;
}

void f_prop_小数转行字符串(S_Props& prop, float32 value, const S_Props& 宽度, const S_Props& 填充字符, const S_Props& 字符方式) {
	f_prop_LineStr(prop) = f_浮点数值转宽字符串(value);
}












S_Props f_alloc_曲线通道Prop(S_曲线通道* data, const std::u16string& name) {
	E_属性值映射方式 值映射类型;
	if (data == nullptr) {
		data = f_an_创建曲线通道(3);
		值映射类型 = E_属性值映射方式::e_属性值映射_独立创建;
	}
	else 值映射类型 = E_属性值映射方式::e_属性值映射_外部指针;
	//S_Props prop = { E_值类型::e_Type_2D曲线1D, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	S_Props prop = f_prop_init(E_值类型::e_Type_2D曲线1D, data, name, 值映射类型);
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

S_Props f_alloc_2DCurveProp(S_曲线* data, const std::u16string& name) {
	E_属性值映射方式 值映射类型;
	if (data == nullptr) {
		data = f_an_创建曲线A();
		值映射类型 = E_属性值映射方式::e_属性值映射_独立创建;
	}
	else 值映射类型 = E_属性值映射方式::e_属性值映射_外部指针;
	//S_Props prop = { E_值类型::e_Type_2D曲线, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	S_Props prop = f_prop_init(E_值类型::e_Type_2D曲线, data, name, 值映射类型);
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

S_Props f_alloc_动画曲线层Prop(S_动画曲线组* data, const std::u16string& name) {
	E_属性值映射方式 值映射类型;
	if (data == nullptr) {
		data = f_an_创建曲线层();
		值映射类型 = E_属性值映射方式::e_属性值映射_独立创建;
	}
	else 值映射类型 = E_属性值映射方式::e_属性值映射_外部指针;
	//S_Props prop = { E_值类型::e_Type_2D曲线1D, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	S_Props prop = f_prop_init(E_值类型::e_Type_2D曲线1D, data, name, 值映射类型);
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

S_Props f_alloc_Prop纹理集(S_TextueSetsProp* data, const std::u16string& name) {
	E_属性值映射方式 值映射类型;
	if (data == nullptr) {
		data = (S_TextueSetsProp*)malloc(sizeof(S_TextueSetsProp));
		(*data) = { {}, 0, 0 };
		(*data).m_纹理集 = f_纹理集_创建();
		值映射类型 = E_属性值映射方式::e_属性值映射_独立创建;
	}
	else 值映射类型 = E_属性值映射方式::e_属性值映射_外部指针;

	S_Props prop = f_prop_init(E_值类型::e_Type_TexSets, data, name, 值映射类型);
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}




S_Props f_prop_创建物体类型属性数据() {
	S_Props prop = f_alloc_EnumProp(nullptr, {
		{ u"空", u"" },
		{ u"网格", u"" },
		{ u"多边形", u"" },
		//{ L"实例", ""},
		//{ L"平行光", ""},
		//{ L"聚光灯", ""},
		//{ L"点光源", ""},
		//{ L"面光源", ""},
		}
	, u"模型类型", 0);

	return prop;
}

S_Props f_prop_创建图像格式类型属性数据() {
	S_Props prop = f_alloc_EnumProp(nullptr, {
		{ u"png", u"" },
		{ u"jpg", u"" },
		{ u"tga", u"" },
		{ u"bmp", u"" },
		{ u"hdr", u"" },
		//{ L"", ""},
		//{ L"平行光", ""},
		//{ L"聚光灯", ""},
		//{ L"点光源", ""},
		//{ L"面光源", ""},


		//{ L"线", ""},
		//{ L"线段", ""},
		//{ L"粒子", ""},
		//{ L"摄像机", ""},

									}
	, u"图像格式", 0);

	return prop;
}

S_Props f_prop_创建图像位宽类型属性数据() {
	S_Props prop = f_alloc_EnumProp(nullptr, {
		{ u"8", u"" },
		{ u"16", u"" },
		{ u"32", u"" },
		//{ L"f32", "" },
		
		}
	, u"图像位宽", 0);

	return prop;
}


S_Props f_prop_创建图像通道类型属性数据() {
	S_Props prop = f_alloc_EnumProp(nullptr, {
		{ u"R", u"" },
		{ u"RGB", u"" },

		{ u"RGBA", u"" },
		//{ L"32", "" },

									}
	, u"图像通道", 0);

	return prop;
}

S_Props f_prop_创建写入方式属性数据() {
	S_Props prop = f_alloc_EnumProp(nullptr, {
								{u"跳过", u""},
								{u"覆盖", u""},
								{u"重命名", u""},
							  }, u"保存方式");
	return prop;
}

S_Props f_prop_创建外部模型格式属性数据() {
	auto 元素 = f_alloc_bool_1DProp(3, u"外部格式");
	元素.m_私有 = true;
	S_PropVecBool* 元素开关 = f_prop_Bool_1D(元素);
	元素开关[0].m_Names = L"FBX"; 元素开关[0].m_ICO = ""; 元素开关[0].m_Value = true;
	元素开关[1].m_Names = L"OBJ"; 元素开关[1].m_ICO = ""; 元素开关[1].m_Value = true;
	元素开关[2].m_Names = L"STL"; 元素开关[2].m_ICO = ""; 元素开关[2].m_Value = true;
	return 元素;
}



E_物体类型 f_prop_物体类型(const S_Props& prop) {
	switch (f_prop_enum(prop)) {
		case 0: return E_物体类型::t_空;
		case 1: return E_物体类型::t_网格物体;
		case 2: return E_物体类型::t_多边形;
		case 3: return E_物体类型::t_实例;
		//case 4: return E_物体类型::t_空;
		//case 5: return E_物体类型::t_空;
		//case 6: return E_物体类型::t_空;
	}
	return E_物体类型::t_空;
}




void f_文件块_写入压缩数据(S_UI8Array* 块, const uint8* data, uint64 size) {

	std::vector<uint8> 压缩点(size);
	uLongf 压缩后大小 = size;
	compress((uint8*)(压缩点.data()), &压缩后大小, data, 压缩后大小);

	uint64 应对ZLIB这种蠢类型 = 压缩后大小;
	f_文件块_写数据块(块, 应对ZLIB这种蠢类型);
	f_core_array_push_back_block((S_Array*)块, (uint8*)(压缩点.data()), 压缩后大小);
}



const uint8* f_文件块_读取压缩数据(const uint8* 下一次读取数据指针, uint8* data, uint64 size) {

	uint64 压缩后大小 = 0;
	下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 压缩后大小);

	uLongf 压缩前大小 = size;
	uncompress(data, &压缩前大小, 下一次读取数据指针, 压缩后大小);

	return &(下一次读取数据指针[压缩后大小]);
}




